<?php

uses(APP_DIR . '/core/form/actions');
uses(APP_DIR . '/core/form/elements');

class Form extends FormBase
{

  const ACTION_NONE = 0;

  const ACTION_INDEX = 1;

  const ACTION_VIEW = 2;

  const ACTION_EDIT = 4;

  const ACTION_CREATE = 8;

  const ACTION_DELETE = 16;

  const ACTION_ALL = 31;

  const ACTION_OPTIONS = 32;

  public $route;

  public $routeParams;

  public $iteratorClass = 'DataViewIterator';

  public $viewClass = 'DataView';

  protected $filters = array();

  /**
   *
   * @return IRepository
   */
  protected $gateway;

  protected $table;

  protected $pk;

  protected $id;

  protected $elements = array();

  protected $actions = array();

  /**
   * @var array
   */
  protected $Action = array();

  public function __construct()
  {
    global $config, $response;

    $this->config = $config;
    //$this->request = Simplify::getRequest();
    $this->response = $response;
    //$this->router = Simplify::getRouter();
  }

  public function getTable()
  {
    return $this->table;
  }

  public function setTable($table)
  {
    $this->table = $table;
  }

  public function getPk()
  {
    return $this->pk;
  }

  public function setPk($pk)
  {
    $this->pk = $pk;
  }

  public function setId($id)
  {
    $this->id = $id;
  }

  public function setRoute($route, $routeParams = null)
  {
    $this->route = $route;
    $this->routeParams = $routeParams;
  }

  public function getId($method = 'GET')
  {
    if (empty($this->id)) {
      $this->id = Simplify::request()->get($this->pk);
    }

    return $this->id;
  }

  public function getTitle()
  {
    return $this->title;
  }

  public function execute($action)
  {
    foreach ($this->filters as $filter) {
      $filter->execute();
    }

    $Action = $this->getAction($action);

    $Action->executeCallback('before' . $Action->getName());

    $response = $Action->execute();

    $Action->executeCallback('after' . $Action->getName());

    return $response;
  }

  public function render($action)
  {
    global $config;

    $Action = $this->getAction($action);

    $content = $Action->render();

    if (! Simplify::request()->ajax() && ! Simplify::request()->json()) {
      $view = $this->getView();

      $view->set('form', $this);
      $view->set('moduleActions', $Action->moduleActions);
      $view->set('layout_content', $content->render());
      $view->set('module_title', $this->title);

      $view->setTemplate($config['views_dir'] .  '/form/form_layout.php');

      return $view;
    }

    return $content;
  }

  public function getView($type = 'PHP')
  {
    $view = View::factory($type);

    return $view;
  }

  /**
   *
   * @return FormAction
   */
  public function getAction($action)
  {
    if (empty($this->Action[$action])) {
      switch ($action) {
        case Form::ACTION_INDEX:
          $this->Action[$action] = new FormAction_Index($this);
          break;

        case Form::ACTION_EDIT:
          $this->Action[$action] = new FormAction_Edit($this);
          break;

        case Form::ACTION_CREATE:
          $this->Action[$action] = new FormAction_Create($this);
          break;

        case Form::ACTION_VIEW:
          $this->Action[$action] = new FormAction_View($this);
          break;

        case Form::ACTION_DELETE:
          $this->Action[$action] = new FormAction_Delete($this);
          break;

        case Form::ACTION_OPTIONS:
          $this->Action[$action] = new FormAction_Options($this);
          break;

        default:
          throw new Exception("Unknown form action: <b>$action</b>");
      }
    }

    return $this->Action[$action];
  }

  public function addFilter(FormFilter $element)
  {
    $element->form = $this;

    $this->filters[] = $element;

    return $element;
  }

  public function getFilters()
  {
    return $this->filters;
  }

  /**
   *
   * @param string $name
   * @param FormElement $element
   * @return FormElement
   */
  public function addElement(FormElement $element, $actions = Form::ACTION_ALL)
  {
    $element->form = $this;
    $element->actions = $actions;

    $this->elements[] = $element;

    return $element;
  }

  public function getElements($action = null)
  {
    return new FormElementIterator($this->elements, $action);
  }

  public function gateway($gateway = null)
  {
    if ($gateway instanceof IRepository) {
      $this->gateway = $gateway;
    }

    if (empty($this->gateway)) {
      $this->gateway = new TableDataGateway($this->table, $this->pk);
    }

    return $this->gateway;
  }

  protected function collectFields($action)
  {
    $fields = array();

    $elements = $this->getElements();

    while ($element = $elements->next()) {
      if ($element->inAction($action)) {
        $fields[] = $element->getField($action);
      }
    }

    return $fields;
  }

}

?>